home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
scd113.arc
/
DEMO1.C
next >
Wrap
Text File
|
1990-06-14
|
19KB
|
723 lines
/*************************************************
** **
** demo1.c **
** **
** SoftC (tm) Dbase Library **
** Address List Demo Program **
** Copyright (C) 1989 by **
** Kim Schumann **
** 16820 3rd St NE **
** Ham Lake, MN 55304 **
** (612) 434-6968 **
** **
** All rights reserved. **
*************************************************/
/*
The Address List Program is a simple program which will create a
database (CUSTOMER.DBF) and two index files. The database record
contains the following fields:
field name type length description
---------- ---- ------ -----------
CODE N 10.0 customer code
DATE D 8 date added to file
FIRSTNAME C 15 first name
LASTNAME C 25 last name
COMPANY C 40 company name
ADDRESS C 30 street address, po box, etc
CITY C 20 city
STATE C 2 state
ZIPCODE C 5 5 digit zip code
AREACODE C 3 telephone area code
TELEPHONE C 8 telephone number
EXTENSION C 4 telephone extension
The index files created are: CUSTCODE.NDX (customer code), and
CUSTNAME.NDX (customer last name).
The program has two main functions: Update/Add new addresses and
List contents of database. It also supports a "Quit" command.
The Update function enables the user to either add a new or find
an existing record. The Add subfunction displays a data entry
screen and then the user steps through the fields filling the
blanks as required (use Control Z to end Add mode). The Find
subfunction allows the user to select what the search type will
be: CODE or LASTNAME. Once the data to be searched for has been
entered, the user will be allowed to scroll forward and backward
through the data. After the data record has been found, the user
is allowed to edit or delete the data record (and keys).
The List function allows the user to select where data will be
displayed (Printer/Screen) and how to sort the data
(Code/Name/Unsorted). The "CODE", "LASTNAME", and "COMPANY"
fields of each data record are displayed.
Seventeen lines of data are output to the screen as a page. The
user is then prompted to continue the display or abort. Data sent
to the printer is continuous with no headings or page numbers.
The program as it stands is barely useable as an address list
manager but its real value is in the demonstration of certain
library functions. However, it could form the basis of a full
featured address list manager, or ...
*/
/*
* header files
*/
#include <sc_base.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#if !defined(__TURBOC__)
#include <graph.h>
#endif
#if !defined(__TURBOC__)
#define gotoxy(x,y); _settextposition(y,x);
#define clrscr(); _clearscreen(_GCLEARSCREEN);
#endif
/*
* global variables
*/
SC_FIELD fields[] = {
"Code", 'n', 10, 0, /* code */
"Date", 'd', 8, 0, /* entry date */
"FirstName", 'c', 15, 0, /* first name */
"LastNAme", 'c', 25, 0, /* last name */
"Company", 'c', 40, 0, /* company name */
"Address", 'c', 30, 0, /* street address, po box, etc */
"City", 'c', 20, 0, /* city */
"State", 'c', 2, 0, /* state */
"ZipCode", 'c', 5, 0, /* 5 digit zip code */
"AreaCode", 'c', 3, 0, /* area code */
"telePhone", 'c', 8, 0, /* telephone number */
"ExTenSion", 'c', 4, 0 /* telephone extension */
};
char dbf, ndx1, ndx2, d[101];
char icterm[] = {15,9,13,26,0}, fterm[] = {13,0};
/*
* function prototypes
*/
void main( void );
void select(char *, char *, char *);
void update( void );
void list( void );
void clearscreen( void );
void add( void );
void find( void );
void clearform( void );
void inputdata( void );
void outputdata( void );
char inputstr( char *, char, char, char, char * );
#if !defined(__TURBOC__)
void clreol( void );
#endif
#if !defined(__TURBOC__)
/* clreol function for microsoftc */
void clreol()
{
struct rccoord rcoord;
char i;
rcoord = _gettextposition();
for (i=(char) rcoord.col; i<80; i++)
putch(' ');
_settextposition(rcoord.row,rcoord.col);
}
#endif
/*
* select will display "msg" starting at column 1 and row 23. It will then
* wait for keyboard input verifying keystrokes against "inver". When a key
* has been pressed which could be found in the verify string that character
* is returned in "ch". Invalid keystrokes are beeped.
*/
void select(msg, inver, ch)
char *msg, *inver, *ch;
{
gotoxy(1,23);
printf("%s",msg);
gotoxy(strlen(msg) + 1,23);
clreol();
do {
*ch = (char) getch();
*ch = toupper(*ch);
if (strchr(inver,*ch) != NULL)
break;
putch(7);
} while (1 != 2);
putch(*ch);
}
/*
* clearscreen will erase the center part of the screen.
*/
void clearscreen()
{
char i;
for (i=4; i<22; i++) {
gotoxy(1,i);
clreol();
}
}
/*
* clearform will clear the field data entry portion of the screen. The field
* names and other text will remain.
*/
void clearform()
{
gotoxy(7,5); printf("%10c",' ');
gotoxy(42,5); clreol();
gotoxy(13,7); printf("%15c",' ');
gotoxy(41,7); clreol();
gotoxy(15,9); clreol();
gotoxy(10,11); clreol();
gotoxy(7,12); printf("%20c",' ');
gotoxy(37,12); printf(" ");
gotoxy(50,12); clreol();
gotoxy(13,14); printf(" ) - ");
gotoxy(41,14); clreol();
}
/*
* inputstr will display the current contents of the field ("data") at the
* proper position on the screen ("x" column, "y" row). It will then wait
* for keyboard input. The routine processes the "right arrow" and "left
* arrow" keys (keypad) to nondestructively move within the field, "delete"
* will delete the character where the cursor is, and "backspace" deletes
* the character immediately to the left of the cursor. "length" determines
* how much data can be entered, and "term" contains a list of special
* characters which will cause inputstr to return to caller.
*/
char inputstr(data,length,x,y,term)
char *data,length,x,y,*term;
{
char p = 0, ch;
gotoxy(x,y);
printf("%s",data);
do {
gotoxy(x+p,y);
ch = (char) getch();
switch (ch) {
case 0:
ch = (char) getch();
switch (ch) {
case 15: /* Shift TAB */
break;
case 75: /* Left Arrow */
if (p > 0)
p--;
else
putch(7);
break;
case 77: /* Right Arrow */
if (p < (char) strlen(data))
p++;
else
putch(7);
break;
case 83: /* Delete Key */
memmove(data+p,data+p+1,length-p);
data[length - 1] = 0;
gotoxy(x,y);
printf("%s",data);
break;
default:
putch(7);
break;
}
break;
case 8: /* Back Space */
if (p > 0) {
memmove(data+p-1,data+p,length-p);
gotoxy(x,y);
printf("%s",data);
p--;
}
else
putch(7);
break;
default:
if (strchr(term,ch) == NULL) {
if ((ch < 32) || (ch > 126) || (p >= length))
putch(7);
else { /* normal character input */
if (strlen(data) == length)
data[length - 1] = 0;
memmove(data+p+1,data+p,length-p);
data[p] = ch;
gotoxy(x,y);
printf("%s",data);
p++;
}
}
break;
}
} while (strchr(term,ch) == NULL);
return(ch);
}
/*
* inputdata calls inputstr successively for each field in the database
* record. This routine will process "tab", "shift tab", "carriage return",
* and "control z" (all done with record).
*/
void inputdata()
{
char tc, n, *p;
double t;
n = 0;
do {
sceclr();
scdrcopy(dbf,SC_OUTPUT);
scdfgets(dbf,n,d);
p = d;
switch(n) {
case 0:
tc = inputstr(d,10,7,5,icterm);
t = atof(d);
p = (char *) &t;
break;
case 1:
sccdxlat(d,d,SC_2ASCII);
tc = inputstr(d,8,42,5,icterm);
break;
case 2:
tc = inputstr(d,15,13,7,icterm);
break;
case 3:
tc = inputstr(d,25,41,7,icterm);
break;
case 4:
tc = inputstr(d,40,15,9,icterm);
break;
case 5:
tc = inputstr(d,30,10,11,icterm);
break;
case 6:
tc = inputstr(d,20,7,12,icterm);
break;
case 7:
tc = inputstr(d,2,37,12,icterm);
break;
case 8:
tc = inputstr(d,5,50,12,icterm);
break;
case 9:
tc = inputstr(d,3,13,14,icterm);
break;
case 10:
tc = inputstr(d,8,17,14,icterm);
break;
case 11:
tc = inputstr(d,4,41,14,icterm);
break;
}
if (scdfput(dbf,n,p) < SC_SUCCESS)
tc = 0;
if ((tc == 9) || (tc == 13)) { /* tab or carriage return */
if (n == 11)
n = 0;
else
n++;
}
else if (tc == 15) { /* translated shift tab */
if (n == 0)
n = 11;
else
n--;
}
} while (tc != 26); /* control Z */
}
/*
* outputdata displays each field of the record along with its name.
*/
void outputdata()
{
gotoxy(1,5); scdfgets(dbf,0,d); printf("Code: %s",d);
gotoxy(30,5); scdfget(dbf,1,d); printf("Entry Date: %s",d);
gotoxy(1,7); scdfgets(dbf,2,d); printf("First Name: %s",d);
gotoxy(30,7); scdfgets(dbf,3,d); printf("Last Name: %s",d);
gotoxy(1,9); scdfgets(dbf,4,d); printf("Company Name: %s",d);
gotoxy(1,11); scdfgets(dbf,5,d); printf("Address: %s",d);
gotoxy(1,12); scdfgets(dbf,6,d); printf("City: %s",d);
gotoxy(30,12); scdfgets(dbf,7,d); printf("State: %s",d);
gotoxy(40,12); scdfgets(dbf,8,d); printf("Zip Code: %s",d);
gotoxy(1,14); scdfgets(dbf,9,d); printf("Telephone: (%s)",d);
gotoxy(17,14); scdfgets(dbf,10,d); printf("%s",d);
gotoxy(30,14); scdfgets(dbf,11,d); printf("Extension: %s",d);
}
/*
* add will solicit a new record, verify that it is new, and if new add
* the data record and keys.
*/
void add()
{
long r;
char *k;
double c;
sceclr();
do {
scdrclear(dbf,SC_OUTPUT);
inputdata();
scdfgetx(dbf,0,&c,SC_OUTPUT);
if (scdkfind(ndx1,(char *) &c,&r,SC_FIRST) == SC_SUCCESS) {
gotoxy(6,19);
printf("ERROR - Duplicate customer code %c",7);
}
else
break;
} while ( 1 != 2 );
scdrput(dbf,&r,SC_ADD);
scdkmake(dbf,ndx1,(void **) &k);
scdkadd(ndx1,k,r);
free(k);
scdkmake(dbf,ndx2,(void **) &k);
scdkadd(ndx2,k,r);
free(k);
}
/*
* find allows user to select which index to search with, to enter a key
* so search for, to single step through index (forward and backward), and
* finally to edit (or delete) the selected record.
*/
void find()
{
char ch, *k, *l, n1[26], n2[26], field, index;
long r;
double c1, c2;
sceclr();
scdrclear(dbf,SC_OUTPUT);
select("Find by: C)ode, N)ame","CN",&ch);
d[0] = 0;
switch (ch) {
case 'C':
ch = inputstr(d,10,7,5,fterm);
c1 = atof(d);
l = (char *) &c1;
field = 0;
index = ndx1;
break;
case 'N':
ch = inputstr(d,25,41,7,fterm);
l = d;
field = 3;
index = ndx2;
break;
}
scdfput(dbf,field,l);
scdkmake(dbf,index,(void **) &l);
if (scdkfind(index,l,&r,SC_FIRST) == SC_SUCCESS) {
do {
scdrget(dbf,r);
outputdata();
select("Find: N)ext, P)revious, Q)uit","NPQ",&ch);
switch (ch) {
case 'N':
scdknext(index,l,&r);
break;
case 'P':
scdkprev(index,l,&r);
break;
}
} while ((ch != 'Q') && (sc_code >= SC_SUCCESS));
if (sc_code >= SC_SUCCESS) {
select("Find: E)dit, D)elete, Q)uit","EDQ",&ch);
switch (ch) {
case 'E':
/* save old data (keys) */
scdfget(dbf,0,&c1);
scdfget(dbf,3,n1);
/* edit record */
scdrcopy(dbf,SC_INPUT);
inputdata();
/* check if keyed data changed */
scdfgetx(dbf,0,&c2,SC_OUTPUT);
scdfgetx(dbf,3,n2,SC_OUTPUT);
if ((c1 != c2) || (strcmp(n1,n2) != 0)) {
/* delete old keys */
scdfput(dbf,0,&c1);
scdfput(dbf,3,n1);
scdkmake(dbf,ndx1,(void **) &k);
scdkdel(ndx1,k,r);
free(k);
scdkmake(dbf,ndx2,(void **) &k);
scdkdel(ndx2,k,r);
free(k);
/* add new keys */
scdfput(dbf,0,&c2);
scdfput(dbf,3,n2);
scdkmake(dbf,ndx1,(void **) &k);
scdkadd(ndx1,k,r);
free(k);
scdkmake(dbf,ndx2,(void **) &k);
scdkadd(ndx2,k,r);
free(k);
}
scdrput(dbf,&r,SC_UPDATE);
break;
case 'D':
scdkmakex(dbf,ndx1,(void **) &k,SC_INPUT);
scdkdel(ndx1,k,r);
free(k);
scdkmakex(dbf,ndx2,(void **) &k,SC_INPUT);
scdkdel(ndx2,k,r);
free(k);
scdrdel(dbf,r);
break;
}
}
}
free(l);
}
/*
* update allows user to select whether to add a new record or to find and
* existing record.
*/
void update()
{
char ch;
long r;
scdrclear(dbf,SC_INPUT);
outputdata();
do {
select("Update: A)dd, F)ind, Q)uit","AFQ",&ch);
switch(ch) {
case 'A':
add();
break;
case 'F':
find();
break;
}
if (ch != 'Q') {
gotoxy(60,2);
scddsize(dbf,&r);
printf("%5ld Records in use",r);
clearform();
}
} while (ch != 'Q');
}
/*
* list allows user to display records on the screen or on a printer, and to
* select which index to use (if any). If displaying on the screen it will
* pause to enable you to view the data. list will show only the active data
* in the file. In other words, records previously deleted will not be
* displayed even though they are still physically in the database.
*/
void list()
{
char co, cs, ch, lc;
long r;
select("Output device: P)rinter, S)creen","PS",&co);
select("Sort by: C)ode, N)ame, U)nsorted","CNU",&cs);
gotoxy(1,23);
printf("Press <Esc> to abort");
gotoxy(21,23); /* printf does not change textposition in MSC */
clreol();
sceclr();
if (cs == 'C')
scdkfirst(ndx1,d,&r);
else if (cs == 'N')
scdkfirst(ndx2,d,&r);
else
r = 1L;
lc = 4;
do {
if (kbhit())
if (getch() == 27)
return;
scdrget(dbf,r);
if (sc_code == SC_SUCCESS) {
if (co == 'P') {
scdfgets(dbf,0,d);
fprintf(stdprn,"%s",d);
scdfgets(dbf,3,d);
fprintf(stdprn,"%s",d);
scdfgets(dbf,4,d);
fprintf(stdprn,"%s\n",d);
}
else {
if (lc == 21) {
gotoxy(1,23);
printf("Press <RETURN> to continue or <Esc> to abort");
gotoxy(45,23);
clreol();
do {
ch = (char) getch();
} while ((ch != 13) || (ch != 27));
if (ch == 27)
return;
gotoxy(1,23);
printf("Press <Esc> to abort");
gotoxy(21,23);
clreol();
clearscreen();
lc = 4;
}
gotoxy(1,lc);
scdfgets(dbf,0,d);
printf("%s",d);
gotoxy(11,lc);
scdfgets(dbf,3,d);
printf("%s",d);
gotoxy(42,lc);
scdfgets(dbf,4,d);
printf("%s",d);
lc++;
}
}
switch (cs) {
case 'C':
scdknext(ndx1,d,&r);
break;
case 'N':
scdknext(ndx2,d,&r);
break;
case 'U':
r += 1L;
break;
}
} while ((sc_code != SC_END) && (sc_code >= SC_SUCCESS));
if (co == 'S') {
gotoxy(1,23);
printf("Press <RETURN>");
gotoxy(15,23);
clreol();
do {
ch = (char) getch();
} while (ch != 13);
}
}
/*
* main opens the data and index files (or creates them if they do not exist).
* The user can then select whether to update the contents of the database,
* or to display them.
*/
void main()
{
char line[80], ch;
long r;
scdinit(20);
memset(line,'-',79);
line[79] = 0;
clrscr();
puts(line);
puts("SoftC Demonstration Database");
puts(line);
gotoxy(1,22);
printf("%s\n\n%s",line,line);
gotoxy(1,4);
if ((scddopen(&dbf,"Customer.dbf") == SC_SUCCESS) &&
(scdnopen(&ndx1,"custcode.ndx") == SC_SUCCESS))
scdnopen(&ndx2,"custname.ndx");
if (sc_code < SC_SUCCESS) {
select("Data files missing. Create new files (Y/N)","YN",&ch);
if (ch == 'Y') {
sceclr();
scddcreate("Customer.dbf",12,fields);
scdncreate("CUSTCODE.NDX",'N',"CODE",8);
scdncreate("CUSTNAME.NDX",'c',"lastname",25);
if ((scddopen(&dbf,"Customer.dbf") == SC_SUCCESS) &&
(scdnopen(&ndx1,"custcode.ndx") == SC_SUCCESS))
scdnopen(&ndx2,"custname.ndx");
if (sc_code < SC_SUCCESS)
exit(1);
}
else
exit(1);
}
gotoxy(60,2);
scddsize(dbf,&r);
printf("%5ld Records in use",r);
do {
select("Select: U)pdate, L)ist, Q)uit","ULQ",&ch);
switch (ch) {
case 'U':
update();
break;
case 'L':
list();
break;
}
clearscreen();
} while (ch != 'Q');
scdterm();
}